
#include <new.h>
#include "ModulsManager\ClassMODmanager.h"
#include "board.h"



MODmanager::MODmanager(ModType *pMT, void **pMS, void **pMR, STATUS_MODUL *psm)
{
  MODUL_STATE ms;
//
  pMtype = (ModType const*)pMT;    pMsets = (void const**)pMS;
  pMrslt = pMR;                    pSM = psm;
//  
  ms.PwrSt = ms.PwrDwnSt = ms.LinkOK = ms.ModuleBad = 0;
  MSt[0] = MSt[1] = MSt[2] = MSt[3] = MSt[4] = ms;
//
}






/*MANAGER_STATUS*/ void MODmanager::INIT_ALL_CLASS_OBJ(void)
{
  uint8_t sl, *pObj, devID, key, ClassSize;
  void *pRslt;
  void const *pMS;
//
  ClassSize = sizeof(ObjBuf)/5;
//
  for(sl=0; sl<5; ++sl)
   {
     pObj = ObjBuf + sl*ClassSize;
     //
     devID = 63-sl;    key = sl+1;
     //
     pRslt = *(pMrslt+sl);    pMS = *(pMsets+sl);
     //
     switch( *(pMtype+sl) )
      {
        case(ModNULL): pBMobj[sl] = new (pObj) BASEmodul(devID, key);
                      break;
        case(ModAIN) : pBMobj[sl] = new (pObj) AINmodul(devID, key, (AinData*)pRslt, (AINsets*)pMS);
                      break;
        case(ModDIN) : pBMobj[sl] = new (pObj) DINmodul(devID, key, (DinData*)pRslt, (DINsets*)pMS);
                      break;
        case(ModADO) : pBMobj[sl] = new (pObj) ADOmodul(devID, key, (ADoData*)pRslt );
                      break;
        case(ModAKRS): //pBMobj[sl] = new (pObj) AKRSmodul(devID,key,pResult,6/*poka*/,(DINsets *)pMS );
                      break;
      }
   }
//
}


/*MANAGER_STATUS*/ void MODmanager::RESET_MODUL(SLOT slot)
{
  uint8_t sl, slB, slE;
  STATUS_MODUL status;
//
  if(slot!=SlotAll)
    {slB = slot - 1; slE = slot;} else {slB = 0; slE = 5;}
  POWER_OFF_MODUL(slot);
//
  for(sl=slB; sl<slE; ++sl)
   {
     POWER_ON_MODUL( (SLOT)(sl+1) );
     if(MSt[sl].PwrSt)
      {
        status = pBMobj[sl]->ScanDevID(63-5);       *(pSM + sl) = status;  
        switch( status )
         {
           case(NO_ANSWER)   : MSt[sl].LinkOK = 0;
                               if( *(pMtype+sl)==ModNULL )  POWER_OFF_MODUL((SLOT)(sl+1));
                            break;
           case(LINE_STRETCH): BAD_MODUL_SCAN(sl);
                            break;
           case(I2C_ERROR)   : MSt[sl].LinkOK = 0;
                               POWER_OFF_MODUL( (SLOT)(sl+1) );
                            break;
                     default : MSt[sl].LinkOK = 1;
          }
       }
    }
//
}



/*MANAGER_STATUS*/ void MODmanager::POWER_OFF_MODUL(SLOT slot)
{
  uint8_t SwOFFmsk;
//
  if(slot==SlotAll) {SwOFFmsk = 0x1F;} else {SwOFFmsk = 1<<slot-1;}
//
  if( SwOFFmsk&1 )  { PWR1_OFF(); MSt[0].PwrSt = 0; }
  if( SwOFFmsk&2 )  { PWR2_OFF(); MSt[1].PwrSt = 0; }
  if( SwOFFmsk&4 )  { PWR3_OFF(); MSt[2].PwrSt = 0; }
  if( SwOFFmsk&8 )  { PWR4_OFF(); MSt[3].PwrSt = 0; }
  if( SwOFFmsk&16 ) { PWR5_OFF(); MSt[4].PwrSt = 0; }
//  
  vTaskDelay(PwrOff_Delay);
}

/*MANAGER_STATUS*/ void MODmanager::POWER_ON_MODUL(SLOT slot)
{
  uint8_t SwONmsk, sl;
//
  if(slot==SlotAll) {SwONmsk = 0x1F;} else {SwONmsk = 1<<slot-1;}
  for(sl=0; sl<5; ++sl)
   {  if( MSt[sl].ModuleBad ) SwONmsk &= ~(1<<sl);  }
//
  if( SwONmsk&1 )  { PWR1_ON(); MSt[0].PwrSt = 1; }
  if( SwONmsk&2 )  { PWR2_ON(); MSt[1].PwrSt = 1; }
  if( SwONmsk&4 )  { PWR3_ON(); MSt[2].PwrSt = 1; }
  if( SwONmsk&8 )  { PWR4_ON(); MSt[3].PwrSt = 1; }
  if( SwONmsk&16 ) { PWR5_ON(); MSt[4].PwrSt = 1; }
//  
  vTaskDelay(PwrOn_Delay);
//
}

/*MANAGER_STATUS*/ void MODmanager::POWER_DOWN_MODUL(SLOT slot)
{
  uint8_t PDWNmsk, sl, NofTry;
//
  if(slot==SlotAll) {PDWNmsk = 0x1F;} else {PDWNmsk = 1<<slot-1;}
  for(sl=0; sl<5; ++sl)
    {
      if( MSt[sl].PwrSt && PDWNmsk&(1<<sl) )
       {
         for(NofTry=5; NofTry; --NofTry)
          {
            if( pBMobj[sl]->WrCR1(PwrDWNon) == NO_ANSWER )
              { MSt[sl].PwrDwnSt = 1;  break; }
            vTaskDelay(PwrDwn_Delay);
          }
       }
    }
//
}

/*MANAGER_STATUS*/ void MODmanager::WAKE_UP_MODUL(SLOT slot)
{
  uint8_t sl;
//
  I2C_SET();  vTaskDelay(1);    I2C_CLR(); vTaskDelay(2);
  I2C_SET();
//
  if( slot!=SlotAll )
    {
      MSt[slot-1].PwrDwnSt = 0;
      for(sl=0; sl<5; ++sl)
       {  if( MSt[sl].PwrDwnSt ) POWER_DOWN_MODUL((SLOT)(sl+1));  }
    }
   else
    {
      for(sl=0; sl<5; ++sl)  {MSt[sl].PwrDwnSt = 0;}
    }
}

void MODmanager::BAD_MODUL_SCAN(uint8_t Sl)
{
  uint8_t sl;
//Power OFF modul & check SDA, SCL
  for(sl=5; sl; --sl)
   {
     if(MSt[Sl].PwrSt)
      {
        POWER_OFF_MODUL((SLOT)(Sl+1));
        if(SDA_SCL_Stretch_Check()) break; 
      }
     if( (++Sl) == 5 ) Sl=0;
   }
//
  if(sl)
    { MSt[Sl].ModuleBad = 1; }
   else
    { /*Something wrong with circuit SDA or SCL*/  }
//
}

static uint32_t	ModMandebug;
void MODmanager::COMMAND_PARSING(COMMANDS com)
{
  uint8_t sl, slE;
//
	ModMandebug++;
  switch(com.cm)
   {
     case(Reset) : RESET_MODUL(com.sl);
             break;
     case(PwrON) : POWER_ON_MODUL(com.sl);
             break;
     case(PwrOFF): POWER_OFF_MODUL(com.sl);
             break;
     case(PwrDwn): POWER_DOWN_MODUL(com.sl);
             break;
     case(WakeUp): WAKE_UP_MODUL(com.sl);
             break;
     case(ScanIS): for(sl=0; sl<5; ++sl)
                    {
                      if(!MSt[sl].ModuleBad && MSt[sl].PwrSt)
                       {
                         *(pSM + sl) = Read_Status(sl);
                         if(MSt[sl].PwrDwnSt) POWER_DOWN_MODUL((SLOT)(sl+1));
                         //if(SMBA_STATE) break;
                       }
                     }
             break;
       default   : if(com.sl==SlotAll)
                     { 
                       for(sl=0; sl<5; ++sl)
                        {
                          if(MSt[sl].PwrDwnSt) { WAKE_UP_MODUL(SlotAll); break; }
                        }
                       sl = 0; slE = 5;
                     }
                    else
                     { 
                       sl = com.sl-1; slE = com.sl;
                       if(MSt[sl].PwrDwnSt) WAKE_UP_MODUL(com.sl);
                     }
                   while(sl<slE)
                    {  BM_COMMAND_PARSING(sl++,com.cm,com.param);  }
   }
}
                   
       
void MODmanager::BM_COMMAND_PARSING(uint8_t sl, COMM com, uint16_t prm)
{
  STATUS_MODUL status;
//
  switch(com)
   {
     case(SetUART)  : status = UNKNOWN_COM;/*yet nothing is being done*/
               break;
     case(SetAKRS)  : status = UNKNOWN_COM;/*yet nothing is being done*/
               break;
     case(DACmode)  : status = UNKNOWN_COM;/*yet nothing is being done*/
               break;
     case(LDiodON)  : status = pBMobj[sl]->WrCR1(LDIODon);
               break;
     case(LDiodOFF) : status = pBMobj[sl]->WrCR1(LDIODoff);
               break;
     case(ResetSC)  : status = pBMobj[sl]->WrCR1(SCrst);
               break;
     case(PwrMode1) : status = pBMobj[sl]->WrCR1(PwrM1on);
               break;
     case(PwrMode2) : status = pBMobj[sl]->WrCR1(PwrM2on);
               break;
     case(SMBA_ON)  : status = pBMobj[sl]->WrCR1(IREQon);
               break;
     case(SMBA_OFF) : status = pBMobj[sl]->WrCR1(IREQoff);
               break;
     case(ChPwrON)  : status = pBMobj[sl]->WriteChPwrON(prm);
               break;
     case(ChPwrOFF) : status = pBMobj[sl]->WriteChPwrOFF(prm);
               break;
     case(StartMeas): status = pBMobj[sl]->WriteStart((uint8_t)(prm>>8),(uint8_t)prm);
               break;
     case(SetAOut)  : status = pBMobj[sl]->SetUpAO();
               break;
     case(SetRelay) : status = pBMobj[sl]->SwitchRO(prm);
               break;
     case(SetDOut)  : status = pBMobj[sl]->SwitchDO(prm);
               break;
     case(RdStatus) : status = Read_Status(sl);
               break;
     case(RdRezult) : status = pBMobj[sl]->ReadCHvals();
  }
//
   *(pSM + sl) = status;
}



STATUS_MODUL MODmanager::Read_Status(uint8_t sl)
{
  STATUS_MODUL status;
  uint8_t cr1st;
//
  status = pBMobj[sl]->ReadStatus();
  if(status == ALL_RIGHT)
   {
     cr1st = pBMobj[sl]->Get_CR1();
     if(cr1st&fSCst)
       {
         if(!V24_STATE) status = pBMobj[sl]->WrCR1(SCrst);
       }
     if(cr1st&fDATArdy) status = pBMobj[sl]->ReadCHvals();
   }
  return status;
}
